{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<!--BOOK_INFORMATION-->\n",
    "<img align=\"left\" style=\"padding-right:10px;\" src=\"figures/PHydro-cover-small.png\">\n",
    "*This is the Jupyter notebook version of the [Python in Hydrology](http://www.greenteapress.com/pythonhydro/pythonhydro.html) by Sat Kumar Tomer.*\n",
    "*Source code is available at [code.google.com](https://code.google.com/archive/p/python-in-hydrology/source).*\n",
    "\n",
    "*The book is available under the [GNU Free Documentation License](http://www.gnu.org/copyleft/fdl.html). If you have comments, corrections or suggestions, please send email to satkumartomer@gmail.com.*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<!--NAVIGATION-->\n",
    "< [Text-File](08.02-Text-File.ipynb) | [Contents](Index.ipynb) | [Pickle](08.04-Pickle.ipynb) >"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 8.3 NetCDF\n",
    "\n",
    "在本节，我们将读取一个NetCDF文件，并写入相同的格式。我们正在使用的这个文件,`rhum.2003.nc`可以从`http://www.unidata.ucar.edu/software/netcdf/examples/files.html`下载。我们将从`Scientific.IO`库中使用`NetCDF`库来读取和写入NetCDF数据，所以让我们先导入它(译者注:限于linux系统，可找替代的如从scipy.io导入netcdf等)。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "#from Scientific.IO import NetCDF as nc\n",
    "from scipy.io import netcdf as nc"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "首先，我们打开这个文件。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "file = nc.netcdf_file('datas/rhum.2003.nc','r')\n",
    "#file = nc.NetCDFFile('datas/rhum.2003.nc','r')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们通过使用`dir`来查看它的属性。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['Conventions',\n",
       " '__class__',\n",
       " '__del__',\n",
       " '__delattr__',\n",
       " '__dict__',\n",
       " '__dir__',\n",
       " '__doc__',\n",
       " '__enter__',\n",
       " '__eq__',\n",
       " '__exit__',\n",
       " '__format__',\n",
       " '__ge__',\n",
       " '__getattribute__',\n",
       " '__gt__',\n",
       " '__hash__',\n",
       " '__init__',\n",
       " '__le__',\n",
       " '__lt__',\n",
       " '__module__',\n",
       " '__ne__',\n",
       " '__new__',\n",
       " '__reduce__',\n",
       " '__reduce_ex__',\n",
       " '__repr__',\n",
       " '__setattr__',\n",
       " '__sizeof__',\n",
       " '__str__',\n",
       " '__subclasshook__',\n",
       " '__weakref__',\n",
       " '_attributes',\n",
       " '_dims',\n",
       " '_mm',\n",
       " '_mm_buf',\n",
       " '_pack_begin',\n",
       " '_pack_int',\n",
       " '_pack_int32',\n",
       " '_pack_int64',\n",
       " '_pack_string',\n",
       " '_read',\n",
       " '_read_att_array',\n",
       " '_read_dim_array',\n",
       " '_read_gatt_array',\n",
       " '_read_numrecs',\n",
       " '_read_values',\n",
       " '_read_var',\n",
       " '_read_var_array',\n",
       " '_recs',\n",
       " '_recsize',\n",
       " '_unpack_int',\n",
       " '_unpack_int32',\n",
       " '_unpack_int64',\n",
       " '_unpack_string',\n",
       " '_write',\n",
       " '_write_att_array',\n",
       " '_write_dim_array',\n",
       " '_write_gatt_array',\n",
       " '_write_numrecs',\n",
       " '_write_values',\n",
       " '_write_var_array',\n",
       " '_write_var_data',\n",
       " '_write_var_metadata',\n",
       " 'base_date',\n",
       " 'close',\n",
       " 'createDimension',\n",
       " 'createVariable',\n",
       " 'description',\n",
       " 'dimensions',\n",
       " 'filename',\n",
       " 'flush',\n",
       " 'fp',\n",
       " 'history',\n",
       " 'maskandscale',\n",
       " 'mode',\n",
       " 'platform',\n",
       " 'sync',\n",
       " 'title',\n",
       " 'use_mmap',\n",
       " 'variables',\n",
       " 'version_byte']"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dir(file)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`title`讲述了数据集的标题，`discription`提供了文件内容的描述。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "b'mean daily NMC reanalysis (2003)'"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "file.title"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "b'Data is from NMC initialized reanalysis\\n(4x/day).  It consists of most variables interpolated to\\npressure surfaces from model (sigma) surfaces.'"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "file.description"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们可以查看数据的维度。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "OrderedDict([('lon', 144), ('lat', 73), ('level', 8), ('time', None)])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "file.dimensions"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们看到，这个数据有四个维度:lat，time，lon,和level，也给出了每个维度的大小。现在，我们可以查看数据中的变量。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "OrderedDict([('level', <scipy.io.netcdf.netcdf_variable at 0x18be7a86080>),\n",
       "             ('lat', <scipy.io.netcdf.netcdf_variable at 0x18be7a86048>),\n",
       "             ('lon', <scipy.io.netcdf.netcdf_variable at 0x18be7a86128>),\n",
       "             ('time', <scipy.io.netcdf.netcdf_variable at 0x18be7a86358>),\n",
       "             ('rhum', <scipy.io.netcdf.netcdf_variable at 0x18be7a862b0>)])"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "file.variables"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这提供了变量名和变量对数据的引用。这意味着这并不会将数据加载到内存中，实际上只是在文中提供一个引用，并且我们只能检索我们想要的变量。我们将得到`rhum`变量的值。首先我们引用一些变量名。然后我们可以看到单元、数据类型，并得到它的值。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "b'millibar'"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "foo = file.variables['level']\n",
    "foo.units"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<bound method netcdf_variable.typecode of <scipy.io.netcdf.netcdf_variable object at 0x0000018BE7A86080>>"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "foo.typecode"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "rhum = foo.getValue"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "现在，我们可以看看变量`rhum`的形状。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "ename": "AttributeError",
     "evalue": "'function' object has no attribute 'shape'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mAttributeError\u001b[0m                         Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-20-9581e678d3e8>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mrhum\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mAttributeError\u001b[0m: 'function' object has no attribute 'shape'"
     ]
    }
   ],
   "source": [
    "rhum.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "第一维表示时间，第二维表示各种压力水平，第三维代表维度，最后一个代表经度。\n",
    "\n",
    "我们可以用相同的方式写入文件。首先我们打开文件来写。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\laihetao\\AppData\\Local\\conda\\conda\\envs\\DataProcess\\lib\\site-packages\\scipy\\io\\netcdf.py:299: RuntimeWarning: Cannot close a netcdf_file opened with mmap=True, when netcdf_variables or arrays referring to its data still exist. All data arrays obtained from such files refer directly to data on disk, and must be copied before the file can be cleanly closed. (See netcdf_file docstring for more information on mmap.)\n",
      "  ), category=RuntimeWarning)\n"
     ]
    }
   ],
   "source": [
    "file = nc.netcdf_file('datas/test.nc','w')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "然后我们可以定义一些类似于标题、描述等的全局属性。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "setattr(file,'title','trial')\n",
    "setattr(file,'description','File generated while testing to write in NetCDF')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "现在我们可以创建一些维度。我们需要定义维度的名称和大小。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "file.createDimension('lat',73)\n",
    "file.createDimension('lon',144)\n",
    "file.createDimension('level',8)\n",
    "file.createDimension('time',65)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "现在我们可以保存这个变量。首先，我们需要从上面创建的列表中定义维度。这个维度应该是元组，注意`lat`之后的冒号,。在此之后，我们可以使用`createVariable`创建变量，我们需要指定变量的名称、格式和维度。我们看到已经创建了一个名称为`lat`的变量并且引用它。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "OrderedDict([('lat', <scipy.io.netcdf.netcdf_variable object at 0x0000018BE7A8E860>)])\n"
     ]
    }
   ],
   "source": [
    "varDims = 'lat',\n",
    "lat = file.createVariable('lat','f',varDims)\n",
    "print(file.variables)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "最终，我们可以将我们的值赋给这个变量。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "lat = np.random.rand(73)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "现在，我们关闭这个文件。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "file.close()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
